#pragma once

#include <gpiod.h>

#include <string>
#include <chrono>
#include <thread>

#include <stdio.h>
#include <unistd.h>
#include <libserialport.h>

#include <iostream>
#include <iomanip>

#include "uart_v2.hpp"
#include "yj_return.hpp"

void t_thread();

typedef enum
{
    RS485_V3_AUTO_DE_CONTROL_MODE,
    RS485_V3_MANUAL_DE_CONTROL_MODE,
} rs485_v3_mode_en,
    *Prs485_v3_mode_en;

class rs485_v3
{
private:
    uart_v2 *_uart;

    struct gpiod_chip *_gpioChip_p;
    struct gpiod_line *_deLine;

    std::string _lastError;
    std::string _gpioChip;
    uint32_t _dePinOffset;

    uint32_t _frame_timeout_ms;
    rs485_v3_mode_en _mode;

    yj_return _flag;

    bool _init_de_pin();
    bool _deinit_de_pin();
    void _set_transmit();
    void _set_receive();

public:
    rs485_v3(uart_v2 *uart,
             std::string gpioChip,
             uint32_t dePinOffset,
             uint32_t frame_timeout_ms);

    rs485_v3(uart_v2 *uart,
             uint32_t frame_timeout_ms);

    ~rs485_v3();

    yj_return rs485_open();
    yj_return rs485_close();
    rs485_v3 &rs485_change_baud_rate(int baud_rate);
    rs485_v3 &rs485_change_send_additonal_byte_time(float additonal_byte_time);
    
    std::mutex& rs485_get_mutex();
    yj_return rs485_get_flag();

    int rs485_send(const uint8_t *buf, int len);
    int rs485_recv(uint8_t *buf, int max_len);         // 按时间断帧
    int rs485_recv_with_length(uint8_t *buf, int len); // 按长度断帧
    void rs485_flush_all();
};
